package com.smedi.ismedi.inmail.core.port.adapter.persistence.repository.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.smedi.ismedi.authority.starter.util.AuthorityUtil;
import com.smedi.ismedi.authority.starter.util.VerifyHelper;
import com.smedi.ismedi.constructionproject.api.dto.response.resp.ProjectResp;
import com.smedi.ismedi.inmail.core.domain.aggregatemodel.Attachment;
import com.smedi.ismedi.inmail.core.domain.aggregatemodel.Organization;
import com.smedi.ismedi.inmail.core.domain.aggregatemodel.Person;
import com.smedi.ismedi.inmail.core.domain.aggregatemodel.Project;
import com.smedi.ismedi.inmail.core.domain.aggregatemodel.announcement.Announcement;
import com.smedi.ismedi.inmail.core.domain.aggregatemodel.announcement.AttachmentKeyAndTime;
import com.smedi.ismedi.inmail.core.domain.aggregatemodel.announcement.Receiver;
import com.smedi.ismedi.inmail.core.domain.dto.*;
import com.smedi.ismedi.inmail.core.domain.repository.AnnouncementRepository;
import com.smedi.ismedi.inmail.core.domain.repository.AttachmentRepository;
import com.smedi.ismedi.inmail.core.domain.repository.PersonRepository;
import com.smedi.ismedi.inmail.core.infrastructure.constant.AnnouncementError;
import com.smedi.ismedi.inmail.core.infrastructure.constant.InmailError;
import com.smedi.ismedi.inmail.core.port.adapter.convert.AdapterConverter;
import com.smedi.ismedi.inmail.core.port.adapter.persistence.model.AnnouncementAttachmentRelationshipEntity;
import com.smedi.ismedi.inmail.core.port.adapter.persistence.model.AnnouncementEntity;
import com.smedi.ismedi.inmail.core.port.adapter.persistence.model.AnnouncementReceiverRelationshipEntity;
import com.smedi.ismedi.inmail.core.port.adapter.persistence.model.TaskRecordEntity;
import com.smedi.ismedi.inmail.core.port.adapter.persistence.mybatis.mapper.AnnouncementAttachmentRelationshipMapper;
import com.smedi.ismedi.inmail.core.port.adapter.persistence.mybatis.mapper.AnnouncementMapper;
import com.smedi.ismedi.inmail.core.port.adapter.persistence.mybatis.mapper.AnnouncementReceiverRelationshipMapper;
import com.smedi.ismedi.inmail.core.port.adapter.persistence.mybatis.mapper.TaskRecordMapper;
import com.smedi.ismedi.inmail.core.port.adapter.service.PersonRemoteApi;
import com.smedi.ismedi.inmail.core.port.adapter.service.ProjectAssignmentRemoteApiService;
import com.smedi.ismedi.inmail.core.port.adapter.service.ProjectRemoteService;
import com.smedi.ismedi.web.starter.exception.LogicException;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Repository;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import static com.smedi.ismedi.inmail.core.infrastructure.constant.AnnouncementStatusEnum.C_PUBLISHED;
import static com.smedi.ismedi.inmail.core.infrastructure.constant.ConstantField.*;
import static com.smedi.ismedi.inmail.core.infrastructure.constant.RecordSourceFromTypeEnum.*;

/**
 * 主体院关系实现类
 *
 * @author niuyanling
 * @date 2021/08/05
 */
@Repository
@AllArgsConstructor
public class AnnouncementRepositoryImpl implements AnnouncementRepository {
    private final AdapterConverter adapterConverter;

    private final AnnouncementMapper announcementMapper;

    private final AnnouncementReceiverRelationshipMapper announcementReceiverRelationshipMapper;

    private final AnnouncementAttachmentRelationshipMapper announcementAttachmentRelationshipMapper;

    private final PersonRepository personRepository;

    private final AttachmentRepository attachmentRepository;

    private final AuthorityUtil authorityUtil;

    private final VerifyHelper verifyHelper;

    private final TaskRecordMapper taskRecordMapper;

    private final ProjectRemoteService projectRemoteService;

    private final ProjectAssignmentRemoteApiService projectAssignmentRemoteApiService;

    private final PersonRemoteApi personRemoteApi;


    @Override
    public Announcement doSave(Announcement announcement) {
        AnnouncementEntity announcementEntity = adapterConverter.announcementToAnnouncementEntity(announcement);
        if (ObjectUtils.isNull(announcement.getId())) {
            announcementMapper.insert(announcementEntity);
        }
        if (ObjectUtils.isNotNull(announcement.getId())) {
            announcementMapper.updateById(announcementEntity);
        }

        // 删除相关关系
        LambdaQueryWrapper<AnnouncementReceiverRelationshipEntity> receiverQueryWrapper = new LambdaQueryWrapper<>();
        receiverQueryWrapper.eq(AnnouncementReceiverRelationshipEntity::getAnnouncementId, announcementEntity.getId());
        announcementReceiverRelationshipMapper.delete(receiverQueryWrapper);

        LambdaQueryWrapper<AnnouncementAttachmentRelationshipEntity> attachmentQueryWrapper = new LambdaQueryWrapper<>();
        attachmentQueryWrapper.eq(AnnouncementAttachmentRelationshipEntity::getAnnouncementId, announcementEntity.getId());
        announcementAttachmentRelationshipMapper.delete(attachmentQueryWrapper);

        List<AnnouncementReceiverRelationshipEntity> announcementReceiverRelationshipEntities = new ArrayList<>();
        if (!verifyHelper.isAvailable(announcement.getReceivers())) {
            throw LogicException.raise(InmailError.RECEIVER_IS_EMPTY);
        }
        for (Receiver receiver : announcement.getReceivers()) {
            AnnouncementReceiverRelationshipEntity announcementReceiverRelationshipEntity = adapterConverter.receiverToAnnouncementReceiverRelationshipEntity(receiver);
            announcementReceiverRelationshipEntity.setAnnouncementId(announcementEntity.getId());
            announcementReceiverRelationshipEntities.add(announcementReceiverRelationshipEntity);
        }
        announcementReceiverRelationshipMapper.insertBatch(announcementReceiverRelationshipEntities);

        List<Attachment> attachments = announcement.getAttachments();
        if (CollectionUtils.isNotEmpty(attachments)) {
            attachments.forEach(attachment -> this.saveAttachment(attachment, announcementEntity.getId()));
        }

        return adapterConverter.announcementEntityToAnnouncement(announcementEntity);
    }

    private void saveReceiver(Receiver receiver, Long announcementId) {
        //先删除 再新增
        AnnouncementReceiverRelationshipEntity announcementReceiverRelationshipEntity = adapterConverter.receiverToAnnouncementReceiverRelationshipEntity(receiver);
        announcementReceiverRelationshipEntity.setAnnouncementId(announcementId);
        announcementReceiverRelationshipMapper.insert(announcementReceiverRelationshipEntity);
    }

    private void saveAttachment(Attachment attachment, Long announcementId) {
        AnnouncementAttachmentRelationshipEntity announcementAttachmentRelationshipEntity = adapterConverter.attachmentToAnnouncementAttachmentRelationshipEntity(attachment);
        announcementAttachmentRelationshipEntity.setAnnouncementId(announcementId);
        announcementAttachmentRelationshipMapper.insert(announcementAttachmentRelationshipEntity);
    }

    @Override
    public Announcement getAnnouncementOne(AnnouncementQuery announcementQuery) {
        LambdaQueryWrapper<AnnouncementEntity> lambdaQueryWrapper = this.announcementQueryToLambdaQueryWrapper(announcementQuery);

        AnnouncementEntity announcementEntity = announcementMapper.selectOne(lambdaQueryWrapper);

        return this.extend(announcementEntity);
    }

    @Override
    public void deleteAnnouncement(AnnouncementQuery announcementQuery) {
        LambdaQueryWrapper<AnnouncementEntity> lambdaQueryWrapper = this.announcementQueryToLambdaQueryWrapper(announcementQuery);

        announcementMapper.delete(lambdaQueryWrapper);

        LambdaQueryWrapper<TaskRecordEntity> taskRecordEntityLambdaQueryWrapper = new LambdaQueryWrapper<>();
        taskRecordEntityLambdaQueryWrapper.eq(TaskRecordEntity::getSourceFromId, announcementQuery.getId());
        taskRecordMapper.delete(taskRecordEntityLambdaQueryWrapper);
    }

    @Override
    public List<Announcement> getAnnouncementList(AnnouncementQuery announcementQuery) {
        LambdaQueryWrapper<AnnouncementEntity> lambdaQueryWrapper = this.announcementQueryToLambdaQueryWrapper(announcementQuery);

        List<AnnouncementEntity> announcementEntities = announcementMapper.selectList(lambdaQueryWrapper);

        return this.extend(announcementEntities);
    }

    @Override
    public Page<Announcement> getAnnouncementPage(AnnouncementQuery announcementQuery) {
        Page<AnnouncementEntity> announcementPage = new Page<>(announcementQuery.getCurrent(), announcementQuery.getSize());

        LambdaQueryWrapper<AnnouncementEntity> lambdaQueryWrapper = this.announcementQueryToLambdaQueryWrapper(announcementQuery);
        if (!verifyHelper.isAvailable(lambdaQueryWrapper)) {
            return new Page<>(announcementQuery.getCurrent(), announcementQuery.getSize());
        }

        Page<AnnouncementEntity> announcementEntityPage = announcementMapper.selectPage(announcementPage, lambdaQueryWrapper);

        List<Announcement> announcements = this.extend(announcementEntityPage.getRecords());

        return adapterConverter.announcementEntityToAnnouncement(announcementEntityPage, announcements);
    }

    @Override
    public List<AttachmentKeyAndTime> getAttachmentKeyList(DownloadFileToZip downloadFileToZip) {
        LambdaQueryWrapper<AnnouncementEntity> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        //只导出状态为已发布的数据
        lambdaQueryWrapper.eq(AnnouncementEntity::getTaskStatus, C_PUBLISHED);
        if (CollectionUtils.isNotEmpty(downloadFileToZip.getIds())) { //勾选
            lambdaQueryWrapper.in(AnnouncementEntity::getId, downloadFileToZip.getIds());
        } else { //条件查询
            List<Long> publishPersonIds = new ArrayList<>();
            if (StringUtils.isNotBlank(downloadFileToZip.getPublisherNameLike())) {
                List<Person> people = personRepository.getPersonList(PersonQuery.builder().nameLike(downloadFileToZip.getPublisherNameLike()).build());
                List<Long> personIds = people.stream().map(Person::getId).collect(Collectors.toList());
                if (CollectionUtils.isNotEmpty(personIds)) {
                    publishPersonIds.addAll(personIds);
                }
            }

            if (StringUtils.isNotBlank(downloadFileToZip.getPublishOrganizationLike())) {
                List<Person> people = personRepository.getPersonList(PersonQuery.builder().organizationNameLike(downloadFileToZip.getPublishOrganizationLike()).build());
                List<Long> personIds = people.stream().map(Person::getId).collect(Collectors.toList());
                if (CollectionUtils.isNotEmpty(personIds)) {
                    publishPersonIds.addAll(personIds);
                }
            }

            lambdaQueryWrapper.in(CollectionUtils.isNotEmpty(publishPersonIds), AnnouncementEntity::getPublisherId, publishPersonIds);
            lambdaQueryWrapper.like(StringUtils.isNotBlank(downloadFileToZip.getTitleLike()), AnnouncementEntity::getTitle, downloadFileToZip.getTitleLike());
            lambdaQueryWrapper.gt(ObjectUtils.isNotNull(downloadFileToZip.getPublishDateTimeStart()), AnnouncementEntity::getPublishDateTime, downloadFileToZip.getPublishDateTimeStart());
            lambdaQueryWrapper.lt(ObjectUtils.isNotNull(downloadFileToZip.getPublishDateTimeEnd()), AnnouncementEntity::getPublishDateTime, downloadFileToZip.getPublishDateTimeEnd());
            lambdaQueryWrapper.in(StringUtils.isNotBlank(downloadFileToZip.getType()), AnnouncementEntity::getType, downloadFileToZip.getType());

        }
        Map<Long, LocalDateTime> announcementIdTimeMap = new HashMap<>();
        List<AnnouncementEntity> announcementEntities = announcementMapper.selectList(lambdaQueryWrapper);
        if (CollectionUtils.isEmpty(announcementEntities)) {
            throw LogicException.raise(AnnouncementError.NOT_EXISTS_PUBLISHED_ATTACHMENT);
        }
        List<Long> announcementIdList = new ArrayList<>();

        announcementEntities.forEach(it -> {
            announcementIdTimeMap.put(it.getId(), it.getPublishDateTime());
            announcementIdList.add(it.getId());
        });
        LambdaQueryWrapper<AnnouncementAttachmentRelationshipEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(AnnouncementAttachmentRelationshipEntity::getAnnouncementId, announcementIdList);
        List<AnnouncementAttachmentRelationshipEntity> list = announcementAttachmentRelationshipMapper.selectList(queryWrapper);

        Set<String> checkSet = new HashSet<>();
        List<AttachmentKeyAndTime> attachmentKeyAndTimeList = new ArrayList<>();
        list.forEach(it -> {
            if (checkSet.add(it.getAttachmentKey())) {
                attachmentKeyAndTimeList.add(AttachmentKeyAndTime.builder()
                        .attachmentKey(it.getAttachmentKey())
                        .publishDatetime(announcementIdTimeMap.get(it.getAnnouncementId()))
                        .build());
            }
        });
        return attachmentKeyAndTimeList;
    }

    private LambdaQueryWrapper<AnnouncementEntity> announcementQueryToLambdaQueryWrapper(AnnouncementQuery announcementQuery) {
        Set<Long> announcementIds = new HashSet<>();
        if (verifyHelper.isAvailable(announcementQuery.getId())) {
            announcementIds.add(announcementQuery.getId());
        }
        if (CollectionUtils.isNotEmpty(announcementQuery.getIds())) {
            announcementIds.addAll(announcementQuery.getIds());
        }

        List<Long> publisherIds = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(announcementQuery.getPublisherIds())) {
            publisherIds.addAll(announcementQuery.getPublisherIds());
        }

        LambdaQueryWrapper<AnnouncementEntity> lambdaQueryWrapper = new LambdaQueryWrapper<>();

        if (ObjectUtils.isNotNull(announcementQuery.getAboutMeId())) {
            lambdaQueryWrapper.and((queryWrapper1) -> {
                queryWrapper1.or().eq(AnnouncementEntity::getPublisherId, announcementQuery.getAboutMeId());
                queryWrapper1.or().eq(AnnouncementEntity::getReviewerId, announcementQuery.getAboutMeId());

                LambdaQueryWrapper<AnnouncementReceiverRelationshipEntity> receiverQueryWrapper = new LambdaQueryWrapper<>();
                receiverQueryWrapper.eq(AnnouncementReceiverRelationshipEntity::getReceiverId, announcementQuery.getAboutMeId());
                List<AnnouncementReceiverRelationshipEntity> announcementReceiverRelationshipEntities = announcementReceiverRelationshipMapper.selectList(receiverQueryWrapper);
                if (CollectionUtils.isNotEmpty(announcementReceiverRelationshipEntities)) {
                    List<Long> announcementIdsByAboutMeId = announcementReceiverRelationshipEntities.stream().map(AnnouncementReceiverRelationshipEntity::getAnnouncementId).collect(Collectors.toList());
                    queryWrapper1.or((queryWrapper2) -> {
                        queryWrapper2.or().in(AnnouncementEntity::getId, announcementIdsByAboutMeId)
                                .eq(AnnouncementEntity::getTaskStatus, C_PUBLISHED);
                    });
                }
            });
        }
        queryKey:
        if (StringUtils.isNotBlank(announcementQuery.getQueryKey())) {
            lambdaQueryWrapper.like(StringUtils.isNotBlank(announcementQuery.getQueryKey()), AnnouncementEntity::getTitle, announcementQuery.getQueryKey());
            List<Person> people = personRepository.getPersonList(PersonQuery.builder().nameLike(announcementQuery.getQueryKey()).build());
            Set<Long> personIds = new HashSet<>();
            if (CollectionUtils.isEmpty(people)) {
                break queryKey;
            }
            for (Person person : people) {
                personIds.add(person.getId());
            }
            lambdaQueryWrapper.or().in(CollectionUtils.isNotEmpty(personIds), AnnouncementEntity::getPublisherId, personIds);
        }

        if (StringUtils.isNotBlank(announcementQuery.getPublisherNameLike())) {
            List<Person> people = personRepository.getPersonList(PersonQuery.builder().nameLike(announcementQuery.getPublisherNameLike()).build());
            List<Long> personIds = people.stream().map(Person::getId).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(announcementQuery.getPublisherIds())) {
                publisherIds = new ArrayList<>(org.apache.commons.collections4.CollectionUtils.intersection(publisherIds, personIds));
            } else {
                publisherIds = personIds;
            }
            if (CollectionUtils.isEmpty(publisherIds)) {
                return null;
            }
        }

        if (StringUtils.isNotBlank(announcementQuery.getPublishOrganizationLike())) {
            List<Person> people = personRepository.getPersonList(PersonQuery.builder().organizationNameLike(announcementQuery.getPublishOrganizationLike()).build());
            List<Long> personIds = people.stream().map(Person::getId).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(announcementQuery.getPublisherIds()) || StringUtils.isNotBlank(announcementQuery.getPublisherNameLike())) {
                publisherIds = new ArrayList<>(org.apache.commons.collections4.CollectionUtils.intersection(publisherIds, personIds));

            } else {
                publisherIds = personIds;
            }
            if (CollectionUtils.isEmpty(publisherIds)) {
                return null;
            }
        }

        receiverId:
        if (ObjectUtils.isNotNull(announcementQuery.getReceiverId())) {
            LambdaQueryWrapper<AnnouncementReceiverRelationshipEntity> receiverQueryWrapper = new LambdaQueryWrapper<>();
            receiverQueryWrapper.eq(AnnouncementReceiverRelationshipEntity::getReceiverId, announcementQuery.getReceiverId());
            List<AnnouncementReceiverRelationshipEntity> announcementReceiverRelationshipEntities = announcementReceiverRelationshipMapper.selectList(receiverQueryWrapper);
            if (CollectionUtils.isEmpty(announcementReceiverRelationshipEntities)) {
                break receiverId;
            }
            announcementIds.addAll(announcementReceiverRelationshipEntities.stream().map(AnnouncementReceiverRelationshipEntity::getAnnouncementId).collect(Collectors.toList()));
        }

        lambdaQueryWrapper.like(StringUtils.isNotBlank(announcementQuery.getTitleLike()), AnnouncementEntity::getTitle, announcementQuery.getTitleLike());
        lambdaQueryWrapper.eq(StringUtils.isNotBlank(announcementQuery.getStatus()), AnnouncementEntity::getTaskStatus, announcementQuery.getStatus());
        lambdaQueryWrapper.gt(ObjectUtils.isNotNull(announcementQuery.getPublishDateTimeStart()), AnnouncementEntity::getPublishDateTime, announcementQuery.getPublishDateTimeStart());
        lambdaQueryWrapper.lt(ObjectUtils.isNotNull(announcementQuery.getPublishDateTimeEnd()), AnnouncementEntity::getPublishDateTime, announcementQuery.getPublishDateTimeEnd());
        lambdaQueryWrapper.in(CollectionUtils.isNotEmpty(publisherIds), AnnouncementEntity::getPublisherId, publisherIds);
        lambdaQueryWrapper.in(CollectionUtils.isNotEmpty(announcementIds), AnnouncementEntity::getId, announcementIds);
        lambdaQueryWrapper.in(CollectionUtils.isNotEmpty(announcementQuery.getStatuses()), AnnouncementEntity::getTaskStatus, announcementQuery.getStatuses());
        lambdaQueryWrapper.in(verifyHelper.isAvailable(announcementQuery.getType()), AnnouncementEntity::getType, announcementQuery.getType());

        lambdaQueryWrapper.orderBy(true, true, AnnouncementEntity::getTaskStatus);
        lambdaQueryWrapper.orderBy(true, false, AnnouncementEntity::getCreateDateTime);

        return lambdaQueryWrapper;
    }

    private Announcement extend(AnnouncementEntity announcementEntity) {
        if (null == announcementEntity) {
            return null;
        }

        List<AnnouncementEntity> announcementEntitys = new ArrayList<>();
        announcementEntitys.add(announcementEntity);
        List<Announcement> announcements = this.extend(announcementEntitys);

        return announcements.get(0);
    }

    private List<Announcement> extend(List<AnnouncementEntity> announcementEntities) {
        if (announcementEntities.isEmpty()) {
            return new ArrayList<>();
        }

        List<Announcement> announcements = new ArrayList<>();

        String personLevel = authorityUtil.getLoginAccess().getPersonLevel();

        Set<Long> personIds = new HashSet<>();
        Set<String> fileSignKeys = new HashSet<>();
        for (AnnouncementEntity announcementEntity : announcementEntities) {
            Long publisherId = announcementEntity.getPublisherId();
            if (null != publisherId) {
                personIds.add(publisherId);
            }
            Long reviewerId = announcementEntity.getReviewerId();
            if (null != reviewerId) {
                personIds.add(reviewerId);
            }
        }

        List<Long> announcementIds = announcementEntities.stream().map(AnnouncementEntity::getId).collect(Collectors.toList());
        Map<Long, List<Receiver>> announcementIdReceiversMap = new HashMap<>(256);
        if (CollectionUtils.isNotEmpty(announcementIds)) {
            LambdaQueryWrapper<AnnouncementReceiverRelationshipEntity> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            List<AnnouncementReceiverRelationshipEntity> announcementReceiverRelationshipEntities = announcementReceiverRelationshipMapper.selectList(lambdaQueryWrapper.in(AnnouncementReceiverRelationshipEntity::getAnnouncementId, announcementIds));
            for (AnnouncementReceiverRelationshipEntity announcementReceiverRelationshipEntity : announcementReceiverRelationshipEntities) {
                Long announcementId = announcementReceiverRelationshipEntity.getAnnouncementId();
                personIds.add(announcementReceiverRelationshipEntity.getReceiverId());
                Receiver receiver = adapterConverter.announcementReceiverRelationshipEntityToReceiver(announcementReceiverRelationshipEntity);
                List<Receiver> receiversByAnnouncement = announcementIdReceiversMap.getOrDefault(announcementId, new ArrayList<>());
                receiversByAnnouncement.add(receiver);
                announcementIdReceiversMap.put(announcementId, receiversByAnnouncement);
            }
        }

        Map<Long, List<Attachment>> announcementIdAttachmentsMap = new HashMap<>(256);
        if (CollectionUtils.isNotEmpty(announcementIds)) {
            LambdaQueryWrapper<AnnouncementAttachmentRelationshipEntity> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            List<AnnouncementAttachmentRelationshipEntity> announcementAttachmentRelationshipEntities = announcementAttachmentRelationshipMapper.selectList(lambdaQueryWrapper.in(AnnouncementAttachmentRelationshipEntity::getAnnouncementId, announcementIds));
            for (AnnouncementAttachmentRelationshipEntity announcementAttachmentRelationshipEntity : announcementAttachmentRelationshipEntities) {
                Long announcementId = announcementAttachmentRelationshipEntity.getAnnouncementId();
                fileSignKeys.add(announcementAttachmentRelationshipEntity.getAttachmentKey());
                Attachment attachment = adapterConverter.announcementAttachmentRelationshipEntityToAttachment(announcementAttachmentRelationshipEntity);
                List<Attachment> attachmentsByAnnouncement = announcementIdAttachmentsMap.getOrDefault(announcementId, new ArrayList<>());
                attachmentsByAnnouncement.add(attachment);
                announcementIdAttachmentsMap.put(announcementId, attachmentsByAnnouncement);
            }
        }

        List<Person> people = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(personIds)) {
            people = personRepository.getPersonList(PersonQuery.builder().ids(new ArrayList<>(personIds)).build());
        }
        Map<Long, Person> idPersonMap = new HashMap<>();
        for (Person person : people) {
            idPersonMap.put(person.getId(), person);
        }

        List<Attachment> files = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(fileSignKeys)) {
            files = attachmentRepository.getAttachmentListByPost(AttachmentQuery.builder().signKeys(new ArrayList<>(fileSignKeys)).build());
        }
        Map<String, Attachment> signKeyAttachmentMap = new HashMap<>();
        for (Attachment attachment : files) {
            signKeyAttachmentMap.put(attachment.getSignKey(), attachment);
        }

        for (AnnouncementEntity announcementEntity : announcementEntities) {
            Announcement announcement = adapterConverter.announcementEntityToAnnouncement(announcementEntity);
            Long publisherId = announcementEntity.getPublisherId();
            if (null != publisherId) {
                announcement.setPublisher(idPersonMap.getOrDefault(publisherId, new Person(publisherId)));
            }
            List<Receiver> receiversByAnnouncement = announcementIdReceiversMap.getOrDefault(announcementEntity.getId(), new ArrayList<>());
            List<Receiver> receivers = new ArrayList<>();
            for (Receiver receiverByAnnouncement : receiversByAnnouncement) {
                Long receiverIdByAnnouncement = receiverByAnnouncement.getId();
                receivers.add(adapterConverter.updateReceiverByPerson(receiverByAnnouncement, idPersonMap.getOrDefault(receiverIdByAnnouncement, new Person(receiverIdByAnnouncement))));
            }
            announcement.setReceivers(receivers);

            Person reviewer = idPersonMap.getOrDefault(announcementEntity.getReviewerId(), new Person(announcementEntity.getReviewerId()));
            announcement.setReviewer(reviewer);
            announcement.getTask().setDealPerson(reviewer);

            List<Attachment> attachmentsByAnnouncement = announcementIdAttachmentsMap.getOrDefault(announcementEntity.getId(), new ArrayList<>());
            List<Attachment> attachments = new ArrayList<>();
            for (Attachment attachmentByAnnouncement : attachmentsByAnnouncement) {
                String attachmentSignKeyByAnnouncement = attachmentByAnnouncement.getSignKey();
                attachments.add(adapterConverter.updateAttachmentByFile(attachmentByAnnouncement, signKeyAttachmentMap.getOrDefault(attachmentSignKeyByAnnouncement, new Attachment(attachmentSignKeyByAnnouncement))));
            }
            announcement.setAttachments(attachments);

            // 统计各个维度的数据
            int receiverTotalNum = 0;
            int readReceiverNum = 0;
            int noReadReceiverNum = 0;
            int receiverTotalNumInInstitutionAndOrganization = 0;
            int readReceiverNumInInstitutionAndOrganization = 0;
            int noReadReceiverNumInInstitutionAndOrganization = 0;
            int receiverTotalNumInInstitution = 0;
            int readReceiverNumInInstitution = 0;
            int noReadReceiverNumInInstitution = 0;
            int receiverTotalNumInOrganization = 0;
            int readReceiverNumInOrganization = 0;
            int noReadReceiverNumInOrganization = 0;
            int receiverTotalNumInProject = 0;
            int readReceiverNumInProject = 0;
            int noReadReceiverNumInProject = 0;
            Map<String, Announcement.Statistics> nameStatisticsInInstitutionAndOrganizationMap = new HashMap<>();
            Map<String, Announcement.Statistics> nameStatisticsInInstitutionMap = new HashMap<>();
            Map<String, Announcement.Statistics> nameStatisticsInOrganizationMap = new HashMap<>();
            Map<String, Map<String, Announcement.Statistics>> nameStatisticsInProjectsMap = new HashMap<>();
            List<Announcement.StatisticsInProject> statisticsInProjects = new ArrayList<>();
            Long currentUserId = authorityUtil.getPersonId();
            List<Long> hrIds = authorityUtil.getDataScope().getOrDefault(ACCESS_HR_ORGANIZATION, new ArrayList<>());
            if(CollectionUtils.isNotEmpty(hrIds) && hrIds.size() == 1 && personLevel.equals("INSTITUTION")){
                personLevel = "ORGANIZATION";
            }

            List<Long> projectIds = authorityUtil.getDataScope().getOrDefault(ACCESS_PROJECT, new ArrayList<>());
            List<Long> orgIds = new ArrayList<>();
            if (CollectionUtils.isNotEmpty(projectIds)) {
                List<ProjectResp> resps = projectRemoteService.getProjectList(ProjectQuery.builder().ids(projectIds).build());
                orgIds = resps.stream().map(ProjectResp::getHrOrganizationId).collect(Collectors.toList());
            } else {
                projectIds = new ArrayList<>();
            }

            for (Receiver receiver : announcement.getReceivers()) {
                if (Objects.equals(receiver.getId(), currentUserId)) {
                    announcement.setReadByCurrentUser(receiver.getIsRead());
                }
                // 统计总体维度
                receiverTotalNum = receiverTotalNum + 1;
                if (receiver.getIsRead()) {
                    readReceiverNum = readReceiverNum + 1;
                }
                if (!receiver.getIsRead()) {
                    noReadReceiverNum = noReadReceiverNum + 1;
                }
                if (ObjectUtils.isNotNull(receiver.getOrganization())) {
                    Organization organization = receiver.getOrganization();
                    if (organization != null && organization.getId() != null && (orgIds.contains(organization.getId()) || personLevel.equals("INSTITUTION")) && !personLevel.equals("PROJECT")) {
                        String name = receiver.getOrganization().getShortName();
                        // 统计管理部门/主体院维度
                        if (receiver.getOrganization().getType().equals(COMPANY_MANAGEMENT_ORGANIZATION) || receiver.getOrganization().getType().equals(PROJECT_MANAGEMENT_ORGANIZATION)) {
                            Announcement.Statistics statistics = nameStatisticsInInstitutionAndOrganizationMap.getOrDefault(name, new Announcement.Statistics(name));
                            statistics.setSourceFromId(receiver.getOrganization().getId());
                            statistics.setSourceFromType(INSTITUTION_OR_ORGANIZATION.name());
                            statistics.setDisplayOrder1(receiver.getOrganization().getDisplayOrder());
                            statistics.getReceivers().add(receiver);
                            statistics.setReceiverTotalNum(statistics.getReceiverTotalNum() + 1);
                            receiverTotalNumInInstitutionAndOrganization = receiverTotalNumInInstitutionAndOrganization + 1;
                            if (receiver.getIsRead()) {
                                statistics.setReadReceiverNum(statistics.getReadReceiverNum() + 1);
                                readReceiverNumInInstitutionAndOrganization = readReceiverNumInInstitutionAndOrganization + 1;
                            }
                            if (!receiver.getIsRead()) {
                                statistics.setNoReadReceiverNum(statistics.getNoReadReceiverNum() + 1);
                                noReadReceiverNumInInstitutionAndOrganization = noReadReceiverNumInInstitutionAndOrganization + 1;
                            }
                            nameStatisticsInInstitutionAndOrganizationMap.put(name, statistics);
                        }
                        // 统计管理部门维度
                        if (receiver.getOrganization().getType().equals(COMPANY_MANAGEMENT_ORGANIZATION) && personLevel.equals("INSTITUTION")) {
                            Announcement.Statistics statistics = nameStatisticsInInstitutionMap.getOrDefault(name, new Announcement.Statistics(name));
                            statistics.setSourceFromId(receiver.getOrganization().getId());
                            statistics.setSourceFromType(INSTITUTION.name());
                            statistics.setDisplayOrder1(receiver.getOrganization().getDisplayOrder());
                            statistics.getReceivers().add(receiver);
                            statistics.setReceiverTotalNum(statistics.getReceiverTotalNum() + 1);
                            receiverTotalNumInInstitution = receiverTotalNumInInstitution + 1;
                            if (receiver.getIsRead()) {
                                statistics.setReadReceiverNum(statistics.getReadReceiverNum() + 1);
                                readReceiverNumInInstitution = readReceiverNumInInstitution + 1;
                            }
                            if (!receiver.getIsRead()) {
                                statistics.setNoReadReceiverNum(statistics.getNoReadReceiverNum() + 1);
                                noReadReceiverNumInInstitution = noReadReceiverNumInInstitution + 1;
                            }
                            nameStatisticsInInstitutionMap.put(name, statistics);
                        }
                        // 统计主体院维度
                        if (receiver.getOrganization().getType().equals(PROJECT_MANAGEMENT_ORGANIZATION)) {
                            Announcement.Statistics statistics = nameStatisticsInOrganizationMap.getOrDefault(name, new Announcement.Statistics(name));
                            statistics.setSourceFromId(receiver.getOrganization().getId());
                            statistics.setSourceFromType(ORGANIZATION.name());
                            statistics.setDisplayOrder1(receiver.getOrganization().getDisplayOrder());
                            statistics.getReceivers().add(receiver);
                            statistics.setReceiverTotalNum(statistics.getReceiverTotalNum() + 1);
                            receiverTotalNumInOrganization = receiverTotalNumInOrganization + 1;
                            if (receiver.getIsRead()) {
                                statistics.setReadReceiverNum(statistics.getReadReceiverNum() + 1);
                                readReceiverNumInOrganization = readReceiverNumInOrganization + 1;
                            }
                            if (!receiver.getIsRead()) {
                                statistics.setNoReadReceiverNum(statistics.getNoReadReceiverNum() + 1);
                                noReadReceiverNumInOrganization = noReadReceiverNumInOrganization + 1;
                            }
                            nameStatisticsInOrganizationMap.put(name, statistics);
                        }
                    }
                }
                // 统计项目维度
                if (CollectionUtils.isNotEmpty(receiver.getProjects()) && ObjectUtils.isNull(receiver.getOrganization())) {
                    List<Project> projects = receiver.getProjects();
                    for (Project project : projects) {
                        String organizationName = project.getOrganization().getShortName();
                        if (!projectIds.contains(project.getId()) && !personLevel.equals("INSTITUTION")) {
                            continue;
                        }
                        String projectName = project.getShortName();
                        Map<String, Announcement.Statistics> nameStatisticsProjectMap = nameStatisticsInProjectsMap.getOrDefault(organizationName, new HashMap<>());
                        Announcement.Statistics statistics = nameStatisticsProjectMap.getOrDefault(projectName, new Announcement.Statistics(projectName));
                        statistics.setSourceFromId(project.getId());
                        statistics.setSourceFromType(PROJECT.name());
                        statistics.setDisplayOrder1(project.getOrganization().getDisplayOrder());
                        statistics.setDisplayOrder2(Integer.valueOf(String.valueOf(project.getId())));
                        statistics.getReceivers().add(receiver);
                        statistics.setReceiverTotalNum(statistics.getReceiverTotalNum() + 1);
                        receiverTotalNumInProject = receiverTotalNumInProject + 1;
                        if (receiver.getIsRead()) {
                            statistics.setReadReceiverNum(statistics.getReadReceiverNum() + 1);
                            readReceiverNumInProject = readReceiverNumInProject + 1;
                        }
                        if (!receiver.getIsRead()) {
                            statistics.setNoReadReceiverNum(statistics.getNoReadReceiverNum() + 1);
                            noReadReceiverNumInProject = noReadReceiverNumInProject + 1;
                        }
                        nameStatisticsProjectMap.put(projectName, statistics);
                        nameStatisticsInProjectsMap.put(organizationName, nameStatisticsProjectMap);
                    }
                }
            }

            for (Map.Entry<String, Map<String, Announcement.Statistics>> organizationEntry : nameStatisticsInProjectsMap.entrySet()) {
                Announcement.StatisticsInProject statisticsInProject = new Announcement.StatisticsInProject();
                statisticsInProject.setName(organizationEntry.getKey());
                ArrayList<Announcement.Statistics> projectStatistics = new ArrayList<>(organizationEntry.getValue().values());
                statisticsInProject.setProjectStatistics(projectStatistics.stream().sorted(Comparator.comparing(Announcement.Statistics::getDisplayOrder2).reversed()).collect(Collectors.toList()));

                statisticsInProjects.add(statisticsInProject);
            }

            // 排序
            ArrayList<Announcement.Statistics> statisticsInInstitutionAndOrganization = new ArrayList<>(nameStatisticsInInstitutionAndOrganizationMap.values());
            List<Announcement.Statistics> statisticsInInstitutionAndOrganizationSorted = statisticsInInstitutionAndOrganization.stream().sorted(Comparator.comparing(Announcement.Statistics::getDisplayOrder1)).collect(Collectors.toList());

            ArrayList<Announcement.Statistics> statisticsInInstitution = new ArrayList<>(nameStatisticsInInstitutionMap.values());
            List<Announcement.Statistics> statisticsInInstitutionSorted = statisticsInInstitution.stream().sorted(Comparator.comparing(Announcement.Statistics::getDisplayOrder1)).collect(Collectors.toList());

            ArrayList<Announcement.Statistics> statisticsInOrganization = new ArrayList<>(nameStatisticsInOrganizationMap.values());
            List<Announcement.Statistics> statisticsInOrganizationSorted = statisticsInOrganization.stream().sorted(Comparator.comparing(Announcement.Statistics::getDisplayOrder1)).collect(Collectors.toList());

            List<Announcement.StatisticsInProject> statisticsInProjectSorted = statisticsInProjects.stream().sorted(Comparator.comparing(Announcement.StatisticsInProject::getDisplayOrder)).collect(Collectors.toList());

            announcement.setStatisticsInInstitutionAndOrganization(statisticsInInstitutionAndOrganizationSorted);
            announcement.setStatisticsInInstitution(statisticsInInstitutionSorted);
            announcement.setStatisticsInOrganization(statisticsInOrganizationSorted);
            announcement.setStatisticsInProject(statisticsInProjectSorted);
            announcement.setReceiverTotalNum(receiverTotalNum);
            announcement.setReceiverTotalNumInInstitutionAndOrganization(receiverTotalNumInInstitutionAndOrganization);
            announcement.setReceiverTotalNumInInstitution(receiverTotalNumInInstitution);
            announcement.setReceiverTotalNumInOrganization(receiverTotalNumInOrganization);
            announcement.setReceiverTotalNumInProject(receiverTotalNumInProject);
            announcement.setReadReceiverNum(readReceiverNum);
            announcement.setReadReceiverNumInInstitutionAndOrganization(readReceiverNumInInstitutionAndOrganization);
            announcement.setReadReceiverNumInInstitution(readReceiverNumInInstitution);
            announcement.setReadReceiverNumInOrganization(readReceiverNumInOrganization);
            announcement.setReadReceiverNumInProject(readReceiverNumInProject);
            announcement.setNoReadReceiverNum(noReadReceiverNum);
            announcement.setNoReadReceiverNumInInstitutionAndOrganization(noReadReceiverNumInInstitutionAndOrganization);
            announcement.setNoReadReceiverNumInInstitution(noReadReceiverNumInInstitution);
            announcement.setNoReadReceiverNumInOrganization(noReadReceiverNumInOrganization);
            announcement.setNoReadReceiverNumInProject(noReadReceiverNumInProject);

            announcements.add(announcement);
        }

        return announcements;
    }
}